<template>
	<div :class="{page: true, 'page-night': isNight, 'page-pink': pageColor.pink, 'page-blue': pageColor.blue, 'page-green': pageColor.green, 'page-orange': pageColor.orange, 'page-gray': pageColor.gray}">
		<!-- 顶栏 -->
		<div class="top-bar">
			<!-- 手机模式显示菜单 -->
			<div class="show-menu-button" @click="showMenuButton">
				<div></div>
				<div></div>
				<div></div>
			</div>
			<!-- 更改颜色主题按钮盒子 -->
			<div class="color-box">
				<div class="text">主题</div>
				<el-tooltip placement="bottom" content="切换为粉色">
					<div class="color-button pink-button" @click="changePageColor('pink')">
						<check class="checked" v-if="pageColor.pink"/>
					</div>
				</el-tooltip>
				<el-tooltip placement="bottom" content="切换为蓝色">
					<div class="color-button blue-button" @click="changePageColor('blue')">
						<check class="checked" v-if="pageColor.blue"/>
					</div>
				</el-tooltip>
				<el-tooltip placement="bottom" content="切换为橙色">
					<div class="color-button orange-button" @click="changePageColor('orange')">
						<check class="checked" v-if="pageColor.orange"/>
					</div>
				</el-tooltip>
				<el-tooltip placement="bottom" content="切换为绿色">
					<div class="color-button green-button" @click="changePageColor('green')">
						<check class="checked" v-if="pageColor.green"/>
					</div>
				</el-tooltip>
				<el-tooltip placement="bottom" content="切换为灰色">
					<div class="color-button gray-button" @click="changePageColor('gray')">
						<check class="checked" v-if="pageColor.gray"/>
					</div>
				</el-tooltip>
			</div>
			<!-- 夜晚模式按钮 -->
			<el-switch class="switch-theme" v-model="isNight" :active-icon="elementIcon.moon" :inactive-icon="elementIcon.sunny"/>
		</div>
		<!-- 主体 -->
		<div class="main-body">
			<!-- 正文内容 -->
			<div class="content" v-html="text" ref="content" @click="closeMenu"></div>
			<!-- 菜单 -->
			<div class="menu" v-if="menuShow">
				<el-tooltip placement="right" v-for="item in menuItems" :key="item.text" :content="item.text">
					<a :style="{paddingLeft: getItemIndentation(item.indentation)}" :href="item.anchor">{{ item.text }}</a>
				</el-tooltip>
			</div>
		</div>
	</div>
</template>

<script>
import { marked } from 'marked';
import highlight from 'highlight.js';
import ClipBoard from 'clipboard';
import renderMathInElement from 'katex/dist/contrib/auto-render.js';
import text from './assets/text.js';

// element-plus消息
import { ElNotification, ElTooltip } from 'element-plus';
// element-plus图标
import { Check, Moon, Sunny } from '@element-plus/icons-vue';

marked.setOptions({
			renderer: new marked.Renderer(),
			highlight: function (code) {
				return highlight.highlightAuto(code).value;
			},
			pedantic: false,
			gfm: true,
			tables: true,
			breaks: false,
			sanitize: false,
			smartLists: true,
			smartypants: false,
			xhtml: false
		}
);

export default {
	components: {
		'el-tooltip': ElTooltip,
		check: Check
	},
	data() {
		return {
			text: undefined,
			// 菜单项
			menuItems: [],
			// 是否显示菜单（手机端）
			menuShow: true,
			// 记录目录是否被解析完成，防止updated无限递归
			menuParsed: false,
			// 是否是夜晚样式
			isNight: false,
			// 是否是手机端
			isMobile: false,
			// 页面颜色主题
			pageColor: {
				pink: true,
				blue: false,
				green: false,
				orange: false,
				gray: false
			},
			// 引入的图标
			elementIcon: {
				moon: Moon,
				sunny: Sunny
			}
		};
	},
	methods: {
		/**
		 * 解析标题生成目录树
		 */
		parseTitle() {
			const doms = this.$refs.content.children;
			// 用于记录最大节点的等级
			let maxLevel = 6;
			// 标题锚点索引
			let index = 0;
			// 逐个获取节点名nodeName属性，找出标题节点
			for (let dom of doms) {
				if (dom.nodeName.startsWith('H')) {
					// 解析当前标题的层级
					let level = parseInt(dom.nodeName.substring(1, 2));
					if (isNaN(level)) {
						continue;
					}
					if (level < maxLevel) {
						maxLevel = level;
					}
					// 设定当前标题id作为锚点
					dom.id = 'title-' + index;
					// 加入到目录列表
					this.menuItems.push({
						text: dom.innerText,
						level: level,
						anchor: '#' + dom.id
					});
					index++;
				}
			}
			// 根据最大标题设定缩进级别
			for (let item of this.menuItems) {
				item.indentation = item.level - maxLevel;
			}
			this.menuParsed = true;
		},
		/**
		 * 获得目录项的缩进长度，css值形式
		 * @param indentationLevel 该项的缩进级别
		 */
		getItemIndentation(indentationLevel) {
			return 'calc(8% + ' + indentationLevel * 7 + 'px)';
		},
		/**
		 * 改变代码样式
		 * @param isNight 是否改为夜晚样式
		 */
		changeCodeStyle(isNight) {
			const preDoms = this.$refs.content.querySelectorAll('pre');
			for (let item of preDoms) {
				if (isNight) {
					item.className = 'pre-night';
				} else {
					item.className = 'pre-day';
				}
			}
		},
		/**
		 * 更改页面颜色主题
		 * @param color 颜色字符串
		 * @param showTip 是否显示提示
		 */
		changePageColor(color, showTip = true) {
			for (let key in this.pageColor) {
				this.pageColor[key] = false;
			}
			switch (color) {
				case 'pink':
					this.pageColor.pink = true;
					break;
				case 'blue':
					this.pageColor.blue = true;
					break;
				case 'green':
					this.pageColor.green = true;
					break;
				case 'orange':
					this.pageColor.orange = true;
					break;
				case 'gray':
					this.pageColor.gray = true;
					break;
				default:
					this.pageColor.pink = true;
					break;
			}
			if (showTip) {
				ElNotification({
					title: '成功！',
					message: '切换主题完成！',
					type: 'success',
					position: 'top-left',
					duration: 1000
				});
			}
			// 存放设定到本地缓存
			window.localStorage.setItem('color', color);
		},
		/**
		 * 手机端显示菜单按钮
		 */
		showMenuButton() {
			this.menuShow = !this.menuShow;
		},
		/**
		 * 手机端点击正文关闭菜单
		 */
		closeMenu() {
			if (this.isMobile) {
				this.menuShow = false;
			}
		},
		/**
		 * 在代码块中添加代码语言名和复制
		 */
		showCodeTypeAndCopy() {
			const pres = this.$refs.content.querySelectorAll('pre');
			let index = 0;
			for (let item of pres) {
				let codeBlock = item.querySelector('code');
				codeBlock.id = 'code-block-' + index;
				let languageName = document.createElement('div');
				languageName.innerText = codeBlock.className.substring(codeBlock.className.indexOf('-') + 1);
				languageName.className = 'code-language';
				let copy = document.createElement('div');
				copy.innerText = 'copy';
				copy.className = 'copy-button';
				copy.setAttribute('data-clipboard-target', '#' + codeBlock.id);
				// 插入到代码块中
				item.appendChild(languageName);
				item.appendChild(copy);
				index++;
			}
			// 实例化剪贴板对象
			const clipBoard = new ClipBoard('.copy-button');
			clipBoard.on('success', (e) => {
				ElNotification({
					title: '成功！',
					message: '复制成功！',
					type: 'success',
					position: 'top-left',
					duration: 750
				});
				// 清除文本选中状态
				e.clearSelection();
			});
			clipBoard.on('error', (e) => {
				ElNotification({
					title: '错误！',
					message: '复制失败！请联系开发者！',
					type: 'error',
					position: 'top-left',
					duration: 750
				});
				// 清除文本选中状态
				e.clearSelection();
			});
		}
	},
	watch: {
		isNight() {
			this.changeCodeStyle(this.isNight);
		}
	},
	mounted() {
		// 读取本地缓存记录的主题并切换
		this.changePageColor(window.localStorage.getItem('color'), false);
		// 读取时间判断是否是晚上
		let time = new Date();
		if (time.getHours() >= 19 || time.getHours() <= 6) {
			this.isNight = true;
		}
		// 读取设备宽度判断是否是移动设备
		if (window.innerWidth <= 768) {
			this.isMobile = true;
			this.menuShow = !this.isMobile;
		}
		// 初始化文本内容
		this.text = marked(text);
	},
	updated() {
		if (!this.menuParsed) {
			this.parseTitle();
			this.showCodeTypeAndCopy();
		}
		this.changeCodeStyle(this.isNight);
		renderMathInElement(this.$refs.content, {
			delimiters: [
				{ left: '$$', right: '$$', display: true },
				{ left: '$', right: '$', display: false },
				{ left: '\\(', right: '\\)', display: true },
				{ left: '\\[', right: '\\]', display: true }
			],
			strict: false,
			throwOnError: false
		});
	}
};
</script>

<style lang="scss">
@font-face {
	font-family: cascadia-code;
	src: url("./assets/fonts/CascadiaCode.woff2");
	font-weight: 350;
}

// 页面平常样式
.page {
	.top-bar {
		position: relative;
		display: flex;
		align-items: center;
		justify-content: flex-end;
		top: 0;
		width: 100%;
		height: 7vh;
		border-bottom: 1px solid #eaecef;
		box-sizing: border-box;

		.show-menu-button {
			position: absolute;
			display: none;
			flex-direction: column;
			justify-content: space-evenly;
			align-items: center;
			left: 1.25vh;
			width: 4.5vh;
			height: 4.5vh;
			border-radius: 4px;
			border: gray 1px solid;

			div {
				width: 75%;
				height: 16%;
				background-color: gray;
				border-radius: 3px;
			}

		}

		.color-box {
			position: relative;
			display: flex;
			justify-content: space-evenly;
			align-items: center;
			margin-right: 24px;
			height: 60%;
			width: 235px;

			.color-button {
				position: relative;
				width: 22px;
				height: 22px;
				border-radius: 50%;
			}

			.checked {
				position: absolute;
				width: 16px;
				left: 3px;
				top: 3px;
			}

			.pink-button {
				background-color: #ffabfe;
			}

			.blue-button {
				background-color: #76adff;
			}

			.orange-button {
				background-color: #ffbc47;
			}

			.green-button {
				background-color: #82ff8b;
			}

			.gray-button {
				background-color: #c4c4c4;
			}
		}

		.switch-theme {
			position: relative;
			margin-right: 3%;
		}

	}

	.main-body {
		position: relative;
		height: 93vh;

		.menu, .content {
			position: absolute;
			overflow-x: hidden;
			overflow-y: scroll;

			// 设定滚动条整体
			&::-webkit-scrollbar {
				width: 5px;
			}

			// 设定滚动条滑块
			&::-webkit-scrollbar-thumb {
				border-radius: 10px;
				background: rgba(0, 0, 0, 0.2);
			}

			// 设定外层轨道滚动槽
			&::-webkit-scrollbar-track {
				border-radius: 0;
				background: rgba(0, 0, 0, 0.1);
			}
		}

		.menu {
			top: 0;
			left: 0;
			margin: 0;
			padding: 0;
			width: 17vw;
			height: 100%;

			a {
				display: block;
				height: 5vh;
				width: 100%;
				text-decoration: none;
				color: black;
				line-height: 5vh;
				box-sizing: border-box;
				padding-right: 5px;
				white-space: nowrap;
				overflow: hidden;
				text-overflow: ellipsis;
				transition: background-color 1.5s ease-in-out;
				user-select: none;

				&:first-child {
					margin-top: 3%;
				}

				&:active {
					transition: background-color 0s linear;
				}
			}
		}

		.content {
			width: 83vw;
			left: 17vw;
			height: 100%;
			box-sizing: border-box;
			padding: 1vh 2vw;

			// 定义二号标题样式
			h2 {
				border-bottom: 1px solid;
			}

			// 定义代码块样式
			pre {
				position: relative;
				display: block;
				border-radius: 4px;
				box-sizing: content-box;
				padding: 13px 9px;
				overflow-x: auto;

				// 设定语言标识和复制按钮
				.code-language, .copy-button {
					position: absolute;
					top: 0;
					user-select: none;
					color: #858585;
				}

				.code-language {
					right: 42px;
				}

				.copy-button {
					right: 5px;
					cursor: pointer;
				}

				// 设定滚动条整体
				&::-webkit-scrollbar {
					height: 4px;
				}

				// 设定滚动条滑块
				&::-webkit-scrollbar-thumb {
					border-radius: 8px;
					background: rgba(0, 0, 0, 0.2);
				}

				// 设定外层轨道滚动槽
				&::-webkit-scrollbar-track {
					border-radius: 0;
					background: rgba(0, 0, 0, 0.1);
				}
			}

			// 定义文字行内代码样式
			p, h2, h3, h4, h5, h6, li, blockquote {
				code {
					display: inline-block;
					line-height: 125%;
					border-radius: 4px;
					padding-left: 5px;
					padding-right: 5px;
					margin-left: 2px;
					margin-right: 2px;
				}
			}

			// 定义代码大小与字体
			code {
				font-family: cascadia-code, serif;
				font-size: 15px;
			}

			// 定义引用块
			blockquote {
				margin: 0;
				border-radius: 4px;
				padding-top: 2px;
				padding-bottom: 2px;

				p {
					margin: 9px;
					word-wrap: break-word;
				}
			}

			// 图片居中
			p {
				img {
					display: block;
					margin: 0 auto;
					// 设定图片最大宽度
					max-width: 95%;
				}
			}

			// 定义列表
			table {
				margin: 0 auto;
				border-collapse: collapse;

				th, td {
					box-sizing: border-box;
					padding: 10px 15px;
					border: 1px solid gainsboro;
				}

				th {
					color: white;
				}

				tr {
					&:nth-child(even) {
						background-color: #e3e3e3;
					}
				}
			}

			// 定义超链接
			a {
				margin-left: 1.5px;
				margin-right: 1.5px;
			}

			// 定义分割线
			hr {
				border-top: none;
			}
		}
	}
}

// 页面夜晚样式
.page-night {
	color: white;
	background-color: #141414;

	.main-body {
		.menu {
			a {
				color: white;
			}
		}

		.content {
			pre {
				// 设定语言标识和复制按钮
				.code-language, .copy-button {
					color: #dadada;
				}
			}

			// 定义列表
			table {
				th {
					color: white;
				}
			}
		}
	}
}

// 手机模式
@media screen and (max-width: 768px) {
	.page {
		.top-bar {
			.show-menu-button {
				display: flex;
			}

			.color-box {
				width: 50%;
				margin-right: 10px;
			}
		}

		.main-body {
			.menu {
				left: 1.25vh;
				height: 45%;
				width: 55%;
				background-color: white;
				border: 1px gray solid;
				border-radius: 4px;
			}

			.content {
				width: 100vw;
				left: 0;
				padding: 2vh 6vw;

				pre {
					// 设定语言标识和复制按钮
					.code-language, .copy-button {
						font-size: 15px;
					}
				}
			}
		}
	}

	.page-night {
		.main-body {
			.menu {
				background-color: #141414;
			}
		}
	}
}

// 引入代码样式
@import "./assets/scss/code/github.scss";
@import "./assets/scss/code/github-dark.scss";
// 引入颜色主题
@import "./assets/scss/color/pink.scss";
@import "./assets/scss/color/blue.scss";
@import "./assets/scss/color/orange.scss";
@import "./assets/scss/color/green.scss";
@import "./assets/scss/color/gray.scss";
</style>